﻿using Sprout.Schedule.Consts;
using Sprout.Schedule.Dtos;
using Sprout.Schedule.Enums;
using Sprout.Schedule.Interfaces;
using Sprout.Schedule.Jobs;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sprout.Core;

namespace Sprout.Schedule.Services
{
    public class JobManagerService : IJobManagerService
    {
        static ISchedulerFactory sf;
        static IScheduler scheduler;
        Lazy<ITaskService> _taskService = ServiceLocator.GetLazyService<ITaskService>();

        ILogger logger;

        public JobManagerService(ILoggerFactory loggerFactory)
        {
            logger = loggerFactory.CreateLogger("调度中心");
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public async Task Initialize()
        {
            sf = new StdSchedulerFactory();
            scheduler = await sf.GetScheduler();

            var taskList = await _taskService.Value.Gets(new TaskQuery());

            if (taskList == null || taskList.Any() == false)
            {
                return;
            }

            foreach (var task in taskList)
            {

                await StartJob(task);
            }


            scheduler.JobFactory = new JobFactory();
            //开始调度器
            if (scheduler.IsStarted == false)
            {
                await scheduler.Start();
            }

            logger.LogInformation("调度任务启动成功，Time=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }


        /// <summary>
        /// 新增计划任务
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public async Task StartJob(TaskInfo item)
        {
            string jobName = GetJobName(item.Id);

            if (await CheckExists(jobName))
            {
                logger.LogError("计划任务，" + item.Name + "已经存在");
                return;
            }

            JobBuilder jobBuilder = null;

            if (item.JobType == JobTypeEnum.LocalJob)
            {
                jobBuilder = JobBuilder.Create(Type.GetType(item.JobFullName));
            }
            else
            {
                //调用API接口的任务
                jobBuilder = JobBuilder.Create<ApiJob>();
            }

            IJobDetail job = jobBuilder
                .WithIdentity(jobName)
                .UsingJobData(JobConst.Task_ID_KEY, item.Id)
                .Build();

            //触发器
            string triggerName = GetTriggerName(item.Id);
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(triggerName)
                .WithCronSchedule(item.CronExpression
                //,x => x.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"))  //设置时区
                )
                .Build();

            await scheduler.ScheduleJob(job, trigger);
            //如果任务状态为禁用
            if (item.Status == TaskStatusEnum.Disabled)
            {
                await PauseJob(item.Id);
            }
        }

        /// <summary>
        /// 判断任务是否存在
        /// </summary>
        /// <param name="jobName"></param>
        /// <returns></returns>
        public async Task<bool> CheckExists(string jobName)
        {
            JobKey jobKey = JobKey.Create(jobName);
            return await scheduler.CheckExists(jobKey);
        }

        /// <summary>
        /// 获取jobName
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public string GetJobName(long jobId)
        {
            return $"job_{jobId}";
        }

        /// <summary>
        /// 获取触发器名称
        /// </summary>
        /// <param name="jobId"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public string GetTriggerName(long jobId, int index = 0)
        {
            return $"trigger_{jobId}_{index}";
        }

        /// <summary>
        /// 暂停任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public async Task PauseJob(long jobId)
        {
            string jobName = GetJobName(jobId);
            JobKey jobKey = JobKey.Create(jobName);
            if (await scheduler.CheckExists(jobKey))
            {
                //暂停触发器
                await scheduler.PauseJob(jobKey);
            }
        }

        /// <summary>
        /// 修改计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <param name="cronExpression"></param>
        /// <returns></returns>
        public async Task UpdateJob(long jobId, string cronExpression)
        {
            if (string.IsNullOrEmpty(cronExpression) || !CronExpression.IsValidExpression(cronExpression))
            {
                throw new Exception("无效的Cron表达式。");
            }

            string jobName = GetJobName(jobId);
            string triggerName = GetTriggerName(jobId);
            TriggerKey triggerKey = new TriggerKey(triggerName);
            if (await scheduler.CheckExists(triggerKey) == false)
            {
                return;
            }
            ICronTrigger cronTrigger = (ICronTrigger)await scheduler.GetTrigger(triggerKey);
            if (cronTrigger == null)
            {
                throw new Exception($"不存在触发器{triggerName}");
            }

            string oldCron = cronTrigger.CronExpressionString;
            if (oldCron != cronExpression)
            {
                var trigger = TriggerBuilder
                .Create()
                .WithIdentity(triggerName)
                .WithCronSchedule(cronExpression)
                .Build();
                //修改一个任务的触发时间，删除原触发器
                await scheduler.RescheduleJob(triggerKey, trigger);
            }
        }

        /// <summary>
        /// 移除一个计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public async Task RemoveJob(long jobId)
        {
            string jobName = GetJobName(jobId);
            string triggerName = GetTriggerName(jobId);
            TriggerKey triggerKey = new TriggerKey(triggerName);
            JobKey jobKey = JobKey.Create(jobName);

            if (!string.IsNullOrEmpty(triggerName))
            {
                //暂停触发器
                await scheduler.PauseTrigger(triggerKey);
                //移除触发器
                await scheduler.UnscheduleJob(triggerKey);
            }

            if (await scheduler.CheckExists(jobKey))
            {
                //删除任务
                await scheduler.DeleteJob(jobKey);
            }
        }

        /// <summary>
        /// 恢复任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public async Task ResumeJob(long jobId)
        {
            string jobName = GetJobName(jobId);
            JobKey jobKey = JobKey.Create(jobName);
            if (await scheduler.CheckExists(jobKey))
            {
                //恢复任务
                await scheduler.ResumeJob(jobKey);
            }
        }

        /// <summary>
        /// 中止任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public async Task Interrupt(long jobId)
        {
            string jobName = GetJobName(jobId);
            JobKey jobKey = JobKey.Create(jobName);
            if (await scheduler.CheckExists(jobKey))
            {
                //中止任务
                await scheduler.Interrupt(jobKey);
            }

        }

        /// <summary>
        /// 运行所有任务。
        /// </summary>
        /// <returns></returns>
        public async Task StartJobs()
        {
            if (scheduler.IsStarted == false)
            {
                await scheduler.Start();
            }
        }

        /// <summary>
        /// 关闭所有任务。
        /// </summary>
        /// <param name="waitForJobsToComplete">是否等待任务完成</param>
        /// <returns></returns>
        public async Task StopJobs(bool waitForJobsToComplete)
        {
            if (!scheduler.IsShutdown)
            {
                await scheduler.Shutdown(waitForJobsToComplete);
            }
        }

        /// <summary>
        /// 暂停所有任务。
        /// </summary>
        /// <returns></returns>
        public async Task PauseAllJobs()
        {
            await scheduler.PauseAll();
        }

        /// <summary>
        /// 恢复所有任务。
        /// </summary>
        /// <returns></returns>
        public async Task ResumeAllJobs()
        {
            await scheduler.ResumeAll();
        }

        /// <summary>
        /// 立即执行任务。
        /// </summary>
        /// <param name="jobId">任务ID</param>
        /// <returns></returns>
        public async Task TriggerJob(long jobId)
        {
            string jobName = GetJobName(jobId);
            JobKey jobKey = JobKey.Create(jobName);
            if (await scheduler.CheckExists(jobKey))
            {
                //立即执行任务
                await scheduler.TriggerJob(jobKey);
            }
        }
    }
}
